package com.jsn.android.audio2.sample

import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Environment
import android.provider.MediaStore
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.TextPaint
import android.text.method.LinkMovementMethod
import android.text.style.ClickableSpan
import android.view.View
import android.widget.ImageView
import android.widget.Toast
import androidx.core.content.FileProvider
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.observe
import com.jsn.android.audio2.R
import com.jsn.android.audio2.databinding.ActivityTakeBinding
import com.jsn.android.audio2.setSafeListener
import com.jsn.android.audio2.toast
import com.jsn.baselibx.ui.BaseActivity
import com.jsn.baselibx.utils.Logs
import kotlinx.android.synthetic.main.activity_take.*
import kotlinx.coroutines.*
import okhttp3.Dispatcher

import java.io.File
import java.io.IOException
import java.lang.Exception
import java.text.SimpleDateFormat
import java.util.*
import kotlin.coroutines.resume

fun Context.toast(obj:Any?){
    obj?.also { Toast.makeText(this,it.toString(),Toast.LENGTH_SHORT).show()}
}

class CameraActivity:BaseActivity<ActivityTakeBinding>(){
    val REQUEST_IMAGE_CAPTURE=1

    override fun getContentView(): Int {
        return R.layout.activity_take
    }

    override fun initUI() {
        imageView=iv_show
        bt_take.setSafeListener {
            dispatchTakePictureIntent()
        }
    }

    lateinit var imageView:ImageView

    override fun initData() {
        setPlay()
        playSpan()
    }

    private fun dispatchTakePictureIntent() {
        Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { takePictureIntent ->
                // Ensure that there's a camera activity to handle the intent
                takePictureIntent.resolveActivity(packageManager)?.also {
                    // Create the File where the photo should go
                    val photoFile: File? = try {
                        createImageFile()
                    } catch (ex: IOException) {
                        // Error occurred while creating the File
                        null
                    }
                    // Continue only if the File was successfully created
                    photoFile?.also {
                        val photoURI: Uri = FileProvider.getUriForFile(
                            this,
                            "com.jsn.android.audio2.fileprovider",
                            it
                        )
                        takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION)
                        takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
                        Logs.e("fuckUri:"+photoURI.toString())
                        startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)
                    }
                } ?:toast("can't take a picture on this device")
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
            val imageBitmap = data?.extras?.get("data") as? Bitmap?
            Logs.e("fuckbitmap${imageBitmap==null}")
            imageBitmap?.also {
                //imageView.setImageBitmap(it)
                setPic(it)
                galleryAddPic()
            }
        }
    }

    @Suppress("DEPRECATION") //fixme: using mediaStore
    private fun galleryAddPic() {
        Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE).also { mediaScanIntent ->
            val f = File(currentPhotoPath)
            mediaScanIntent.data = Uri.fromFile(f)
            sendBroadcast(mediaScanIntent)
        }
    }


    var currentPhotoPath: String?=null

    @SuppressLint("SimpleDateFormat")
    @Throws(IOException::class)
    private fun createImageFile(): File {
        // Create an image file name
        val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
        val storageDir: File? = getExternalFilesDir(Environment.DIRECTORY_PICTURES)
        return File.createTempFile(
            "JPEG_${timeStamp}_", /* prefix */
            ".jpg", /* suffix */
            storageDir /* directory */
        ).apply {
            // Save a file: path for use with ACTION_VIEW intents
            currentPhotoPath = absolutePath
            Logs.e("fuckPath:"+currentPhotoPath)
        }
    }
    private fun setPic(it: Bitmap) {
        // Get the dimensions of the View
        val targetW: Int = imageView.width
        val targetH: Int = imageView.height

        val bmOptions = BitmapFactory.Options().apply {
            // Get the dimensions of the bitmap
            inJustDecodeBounds = true

            val photoW: Int = it.width
            val photoH: Int = it.height

            // Determine how much to scale down the image
            val scaleFactor: Int = Math.min(photoW / targetW, photoH / targetH)

            // Decode the image file into a Bitmap sized to fill the View
            inJustDecodeBounds = false
            inSampleSize = scaleFactor
            inPurgeable = true
        }
        BitmapFactory.decodeFile(currentPhotoPath, bmOptions)?.also { bitmap ->
            imageView.setImageBitmap(bitmap)
        }
    }

    val job= SupervisorJob()

    val newScope = CoroutineScope(job+Dispatchers.Default)

    var currentjob:Job?=null

    val jobActive=MutableLiveData<Boolean>(false) //no job is active

    fun setPlay(){
        bt_play.setOnClickListener {
            jobActive.value=true
            testStructuredConrurrency() //start a coroutine
        }
        bt_stop.setOnClickListener {
            currentjob?.cancel()
        }

        jobActive.observe(this){isActive->
            bt_play.isEnabled=!isActive
            bt_stop.isEnabled=isActive
            pb_suspending.visibility=if(isActive) View.VISIBLE else View.GONE
        }
        lifecycleScope

    }

    override fun onDestroy() {
        super.onDestroy()
        job.cancel()
    }

    fun testStructuredConrurrency(){
        //SupervisorJob
        currentjob = newScope.launch(Dispatchers.IO) {  //start a new coroutine override the coroutine context,here we change the Dispatcher
            val res =
                try {
                    fetchString()
                } catch (e: Exception) {
                    Logs.e("catch a cancellationException ? ${e is CancellationException}")
                    null
                } finally {
                    //do clean up here
                    //cancelled
                    jobActive.postValue(false)
                }
        }
    }

    suspend fun fetchString():String= suspendCancellableCoroutine<String> { cancellableContinuation ->
            Logs.e("playresumed")
        val exitPoint = System.currentTimeMillis() + 5000
        while(System.currentTimeMillis()<exitPoint){ //keep computing which wastes cpu so that cancellationException won't be thrown when Job.cancell() called
            currentjob?.ensureActive() //it will not throw because it  holds cpu ,so we invoke this method here to throw which make our cotoutine cancellable
        }
        cancellableContinuation.resume("hahaha")
    }

    fun playSpan(){
        val builer = SpannableStringBuilder(tv_1.text)
        val span=object :ClickableSpan(){
            override fun onClick(widget: View) {
                toast("span works")
            }

            override fun updateDrawState(ds: TextPaint) {
                super.updateDrawState(ds)
                ds.setColor(ds.linkColor)
                //ds.isUnderlineText=false
            }
        }
        builer.setSpan(span,2,4,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
        tv_1.movementMethod = LinkMovementMethod.getInstance()
        tv_1.text=builer
    }



}